package mongo

import (
	"sync"
	"time"

	"gitee.com/dayu1985/framework/context"

	mgo "gopkg.in/mgo.v2"
)

type Database struct {
	*mgo.Database
	prefix string
}

func (database *Database) C(db string) *mgo.Collection {
	return database.Database.C(database.prefix + db)
}

func NewMongoDB(uri string, db string, prefix string) *Database {

	sess, err := mgo.Dial(uri)

	if err != nil {
		panic(err)
	}

	db = prefix + db

	//保证连接可用性 - 断线自动重连
	go func(sess *mgo.Session) {
		for {
			select {
			case <-time.After(5 * time.Second):
				sess.Refresh()
			}
		}
	}(sess)

	return &Database{
		sess.DB(db), prefix,
	}
}

var mutex = sync.Mutex{}
var dbs = map[string]*Database{}

func DefaultMongoDB(c *context.Configuration) *Database {
	return MustMongoDB(c, context.SECTION_DATABASE)
}

func MustMongoDB(c *context.Configuration, section string) *Database {

	mutex.Lock()
	defer mutex.Unlock()

	if dbs[section] != nil {
		return dbs[section]
	}

	url := c.INI.MustValue(section, "mongodb", "")

	if url == "" {
		panic("未定义数据库...")
	}

	sess, err := mgo.Dial(url)

	if err != nil {
		panic(err)
	}

	prefix := c.INI.MustValue(section, "mongodb.prefix", "")

	db := c.INI.MustValue(section, "mongodb.db", "")
	if db != "" {
		db = prefix + db
	}

	dbs[section] = &Database{
		sess.DB(db), prefix,
	}

	//保证连接可用性 - 断线自动重连
	go func(sess *mgo.Session) {
		for {
			select {
			case <-time.After(5 * time.Second):
				sess.Refresh()
			}
		}
	}(sess)

	return dbs[section]
}

type MongoOp func(c *mgo.Collection) error

func Do(c *mgo.Collection, fn func(c *mgo.Collection) error) error {

	sess := c.Database.Session.Copy()
	defer sess.Close()

	db := c.Database.Name
	coll := c.Name

	return fn(sess.DB(db).C(coll))
}

func Do_Database(d *mgo.Database, fn func(d *mgo.Database) error) error {

	sess := d.Session.Copy()
	defer sess.Close()

	return fn(sess.DB(d.Name))
}
